<template>
  <div
    class="app-window"
    :class="{ 
      'active': window.isActive, 
      'maximized': window.isMaximized 
    }"
    :style="windowStyle"
    @mousedown="activateWindow"
    ref="windowRef"
  >
    <!-- 窗口标题栏 -->
    <div 
      class="window-header" 
      @mousedown="startDrag"
      @dblclick="toggleMaximize"
    >
      <div class="window-title">
        <el-icon v-if="window.icon"><component :is="window.icon" /></el-icon>
        <span>{{ window.title }}</span>
      </div>
      <div class="window-controls">
        <el-button 
          class="control-btn minimize-btn" 
          @click.stop="minimizeWindow"
          type="text"
        >
          <el-icon><Minus /></el-icon>
        </el-button>
        <el-button 
          class="control-btn maximize-btn" 
          @click.stop="toggleMaximize"
          type="text"
        >
          <el-icon v-if="window.isMaximized"><FullScreen /></el-icon>
          <el-icon v-else><Crop /></el-icon>
        </el-button>
        <el-button 
          class="control-btn close-btn" 
          @click.stop="closeWindow"
          type="text"
        >
          <el-icon><Close /></el-icon>
        </el-button>
      </div>
    </div>

    <!-- 窗口内容 -->
    <div class="window-content">
      <iframe
        v-if="window.url"
        :src="window.url"
        frameborder="0"
        class="app-iframe"
        ref="iframeRef"
        :sandbox="sandboxAttributes"
        :allow="allowAttributes"
      ></iframe>
      <component 
        v-else-if="window.component" 
        :is="resolveComponent(window.component)" 
        class="app-component"
      />
      <div v-else class="app-error">
        <el-empty description="应用加载失败">
          <el-button type="primary" @click="closeWindow">关闭</el-button>
        </el-empty>
      </div>
    </div>

    <!-- 窗口调整大小的句柄 -->
    <div v-if="!window.isMaximized" class="resize-handle top-left" @mousedown.stop="startResize('top-left')"></div>
    <div v-if="!window.isMaximized" class="resize-handle top" @mousedown.stop="startResize('top')"></div>
    <div v-if="!window.isMaximized" class="resize-handle top-right" @mousedown.stop="startResize('top-right')"></div>
    <div v-if="!window.isMaximized" class="resize-handle right" @mousedown.stop="startResize('right')"></div>
    <div v-if="!window.isMaximized" class="resize-handle bottom-right" @mousedown.stop="startResize('bottom-right')"></div>
    <div v-if="!window.isMaximized" class="resize-handle bottom" @mousedown.stop="startResize('bottom')"></div>
    <div v-if="!window.isMaximized" class="resize-handle bottom-left" @mousedown.stop="startResize('bottom-left')"></div>
    <div v-if="!window.isMaximized" class="resize-handle left" @mousedown.stop="startResize('left')"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, markRaw, defineAsyncComponent } from 'vue'
import { Minus, Close, FullScreen, Crop } from '@element-plus/icons-vue'
import type { AppWindow as AppWindowType, AppMessage, AppSDK } from '@/types/app'
import { useUserStore } from '@/stores/user'
import axios from 'axios'
// 导入我们的自定义应用组件
import TodoApp from '@/components/TodoApp.vue'
import TextEditorApp from '@/components/TextEditorApp.vue'
import ImageViewerApp from '@/components/ImageViewerApp.vue'

const props = defineProps<{
  window: AppWindowType
}>()

const emit = defineEmits<{
  (e: 'activate', windowId: string): void
  (e: 'close', windowId: string): void
  (e: 'minimize', windowId: string): void
  (e: 'maximize', windowId: string): void
  (e: 'restore', windowId: string): void
  (e: 'update-position', windowId: string, x: number, y: number): void
  (e: 'update-size', windowId: string, width: number, height: number): void
}>()

const windowRef = ref<HTMLElement | null>(null)
const iframeRef = ref<HTMLIFrameElement | null>(null)
const userStore = useUserStore()

// 计算窗口样式
const windowStyle = computed(() => {
  const style: Record<string, any> = {
    width: props.window.isMaximized ? '100%' : `${props.window.width}px`,
    height: props.window.isMaximized ? '100%' : `${props.window.height}px`,
    zIndex: props.window.zIndex,
  }

  if (!props.window.isMaximized) {
    style.left = `${props.window.x}px`
    style.top = `${props.window.y}px`
  } else {
    style.left = '0'
    style.top = '0'
  }

  return style
})

// 计算沙箱属性
const sandboxAttributes = computed(() => {
  // 默认禁用所有权限
  const permissions = [
    'allow-scripts',
    'allow-same-origin',
  ]
  
  // 根据应用配置添加权限
  // 这里可以根据应用的配置动态添加沙箱权限
  
  return permissions.join(' ')
})

// 计算allow属性
const allowAttributes = computed(() => {
  const permissions: string[] = []
  
  // 根据应用配置添加允许的功能
  // 例如: clipboard-read, clipboard-write, camera, microphone等
  
  return permissions.join('; ')
})

// 激活窗口
const activateWindow = () => {
  if (!props.window.isActive) {
    emit('activate', props.window.id)
  }
}

// 关闭窗口
const closeWindow = () => {
  emit('close', props.window.id)
}

// 最小化窗口
const minimizeWindow = () => {
  emit('minimize', props.window.id)
}

// 最大化窗口
const maximizeWindow = () => {
  if (!props.window.isMaximized) {
    emit('maximize', props.window.id)
  }
}

// 还原窗口
const restoreWindow = () => {
  if (props.window.isMaximized) {
    emit('restore', props.window.id)
  }
}

// 切换最大化/还原状态
const toggleMaximize = () => {
  if (props.window.isMaximized) {
    emit('restore', props.window.id)
  } else {
    emit('maximize', props.window.id)
  }
}

// 拖动窗口相关变量
const isDragging = ref(false)
const dragStartX = ref(0)
const dragStartY = ref(0)
const windowStartX = ref(0)
const windowStartY = ref(0)

// 开始拖动窗口
const startDrag = (event: MouseEvent) => {
  if (props.window.isMaximized) return
  
  isDragging.value = true
  dragStartX.value = event.clientX
  dragStartY.value = event.clientY
  windowStartX.value = props.window.x
  windowStartY.value = props.window.y
  
  // 激活窗口
  activateWindow()
  
  // 添加事件监听
  document.addEventListener('mousemove', handleDrag)
  document.addEventListener('mouseup', stopDrag)
}

// 处理拖动过程
const handleDrag = (event: MouseEvent) => {
  if (!isDragging.value) return
  
  const deltaX = event.clientX - dragStartX.value
  const deltaY = event.clientY - dragStartY.value
  
  const newX = windowStartX.value + deltaX
  const newY = windowStartY.value + deltaY
  
  emit('update-position', props.window.id, newX, newY)
}

// 结束拖动
const stopDrag = () => {
  isDragging.value = false
  
  // 移除事件监听
  document.removeEventListener('mousemove', handleDrag)
  document.removeEventListener('mouseup', stopDrag)
}

// 调整窗口大小相关变量
const isResizing = ref(false)
const resizeDirection = ref('')
const resizeStartX = ref(0)
const resizeStartY = ref(0)
const windowStartWidth = ref(0)
const windowStartHeight = ref(0)

// 开始调整窗口大小
const startResize = (direction: string) => {
  isResizing.value = true
  resizeDirection.value = direction
  
  // 修复类型错误，正确获取事件参数
  const evt = window.event as MouseEvent
  resizeStartX.value = evt?.clientX || 0
  resizeStartY.value = evt?.clientY || 0
  
  windowStartWidth.value = props.window.width
  windowStartHeight.value = props.window.height
  windowStartX.value = props.window.x
  windowStartY.value = props.window.y
  
  // 激活窗口
  activateWindow()
  
  // 添加事件监听
  document.addEventListener('mousemove', handleResize)
  document.addEventListener('mouseup', stopResize)
}

// 处理调整窗口大小
const handleResize = (event: MouseEvent) => {
  if (!isResizing.value) return
  
  const deltaX = event.clientX - resizeStartX.value
  const deltaY = event.clientY - resizeStartY.value
  
  let newWidth = windowStartWidth.value
  let newHeight = windowStartHeight.value
  let newX = props.window.x
  let newY = props.window.y
  
  // 根据调整方向计算新的宽高和位置
  switch (resizeDirection.value) {
    case 'top-left':
      newWidth = windowStartWidth.value - deltaX
      newHeight = windowStartHeight.value - deltaY
      newX = windowStartX.value + deltaX
      newY = windowStartY.value + deltaY
      break
    case 'top':
      newHeight = windowStartHeight.value - deltaY
      newY = windowStartY.value + deltaY
      break
    case 'top-right':
      newWidth = windowStartWidth.value + deltaX
      newHeight = windowStartHeight.value - deltaY
      newY = windowStartY.value + deltaY
      break
    case 'right':
      newWidth = windowStartWidth.value + deltaX
      break
    case 'bottom-right':
      newWidth = windowStartWidth.value + deltaX
      newHeight = windowStartHeight.value + deltaY
      break
    case 'bottom':
      newHeight = windowStartHeight.value + deltaY
      break
    case 'bottom-left':
      newWidth = windowStartWidth.value - deltaX
      newHeight = windowStartHeight.value + deltaY
      newX = windowStartX.value + deltaX
      break
    case 'left':
      newWidth = windowStartWidth.value - deltaX
      newX = windowStartX.value + deltaX
      break
  }
  
  // 更新窗口大小
  if (newWidth >= 200 && newHeight >= 150) {
    emit('update-size', props.window.id, newWidth, newHeight)
    
    // 更新窗口位置
    if (newX !== props.window.x || newY !== props.window.y) {
      emit('update-position', props.window.id, newX, newY)
    }
  }
}

// 结束调整窗口大小
const stopResize = () => {
  isResizing.value = false
  
  // 移除事件监听
  document.removeEventListener('mousemove', handleResize)
  document.removeEventListener('mouseup', stopResize)
}

// SDK实现
const createAppSDK = (): AppSDK => {
  return {
    // 核心方法
    getAppInfo: async () => {
      return {
        id: String(props.window.appId),
        name: props.window.title,
        description: '',
        version: '1.0.0',
        icon: props.window.icon,
        developer: '',
        category: '',
        tags: [],
        screenshots: [],
        downloadCount: 0,
        rating: 0,
        status: 'published',
        createdAt: '',
        updatedAt: ''
      }
    },
    getAppPermissions: async () => {
      return []
    },
    
    // 窗口管理
    closeWindow: () => {
      closeWindow()
    },
    minimizeWindow: () => {
      minimizeWindow()
    },
    maximizeWindow: () => {
      maximizeWindow()
    },
    restoreWindow: () => {
      restoreWindow()
    },
    
    // 数据存储
    getData: async (key: string) => {
      const storageKey = `app_${props.window.appId}_${key}`
      return localStorage.getItem(storageKey)
    },
    setData: async (key: string, value: any) => {
      const storageKey = `app_${props.window.appId}_${key}`
      localStorage.setItem(storageKey, value)
    },
    removeData: async (key: string) => {
      const storageKey = `app_${props.window.appId}_${key}`
      localStorage.removeItem(storageKey)
    },
    
    // 通知
    showNotification: async (title: string, options?: NotificationOptions) => {
      if (!("Notification" in window)) {
        console.error("此浏览器不支持桌面通知")
        return
      }
      
      if (Notification.permission === "granted") {
        new Notification(title, options)
      } else if (Notification.permission !== "denied") {
        const permission = await Notification.requestPermission()
        if (permission === "granted") {
          new Notification(title, options)
        }
      }
    },
    
    // 系统集成
    openUrl: async (url: string) => {
      window.open(url, '_blank')
    },
    copyToClipboard: async (text: string) => {
      await navigator.clipboard.writeText(text)
    },
    readFromClipboard: async () => {
      return await navigator.clipboard.readText()
    },
    
    // 文件操作
    openFile: async (options?: { accept?: string }) => {
      return new Promise<File | null>((resolve) => {
        const input = document.createElement('input')
        input.type = 'file'
        if (options?.accept) {
          input.accept = options.accept
        }
        
        input.onchange = (event) => {
          const target = event.target as HTMLInputElement
          const file = target.files?.[0] || null
          resolve(file)
        }
        
        input.click()
      })
    },
    saveFile: async (content: Blob, filename: string) => {
      const url = URL.createObjectURL(content)
      const a = document.createElement('a')
      a.href = url
      a.download = filename
      a.click()
      URL.revokeObjectURL(url)
    },
    
    // 通信
    sendMessage: async (targetAppId: string, message: any) => {
      const messageData: AppMessage = {
        type: 'app-message',
        payload: message,
        source: String(props.window.appId),
        target: targetAppId,
        timestamp: Date.now()
      }
      
      window.parent.postMessage(messageData, '*')
    },
    onMessage: (callback: (message: any, sourceAppId: string) => void) => {
      const handler = (event: MessageEvent) => {
        const data = event.data as AppMessage
        if (data && data.type === 'app-message' && data.target === String(props.window.appId)) {
          callback(data.payload, data.source)
        }
      }
      
      window.addEventListener('message', handler)
      
      return () => {
        window.removeEventListener('message', handler)
      }
    }
  }
}

// 注入SDK到iframe
const injectSDK = () => {
  if (!iframeRef.value || !iframeRef.value.contentWindow) return
  
  const sdk = createAppSDK()
  const sdkString = `window.AppSDK = ${JSON.stringify(sdk)}`
  
  try {
    // 注入SDK脚本
    const script = document.createElement('script')
    script.textContent = sdkString
    iframeRef.value.contentDocument?.head.appendChild(script)
    
    // 建立消息通道
    window.addEventListener('message', handleMessage)
  } catch (error) {
    console.error('SDK注入失败', error)
  }
}

// 处理iframe消息
const handleMessage = (event: MessageEvent) => {
  const data = event.data
  
  // 验证消息来源
  if (!iframeRef.value || event.source !== iframeRef.value.contentWindow) {
    return
  }
  
  // 处理SDK方法调用
  if (data && data.type === 'sdk-call') {
    const { method, params, callId } = data
    
    // 创建SDK实例
    const sdk = createAppSDK()
    
    // 调用方法
    if (method in sdk) {
      try {
        // @ts-ignore
        const result = sdk[method](...(params || []))
        
        // 处理Promise结果
        if (result instanceof Promise) {
          result
            .then(value => {
              sendResponse(callId, { success: true, data: value })
            })
            .catch(error => {
              sendResponse(callId, { success: false, error: error.message })
            })
        } else {
          sendResponse(callId, { success: true, data: result })
        }
      } catch (error: any) {
        sendResponse(callId, { success: false, error: error.message })
      }
    } else {
      sendResponse(callId, { success: false, error: `方法 ${method} 不存在` })
    }
  }
}

// 发送响应
const sendResponse = (callId: string, response: any) => {
  if (!iframeRef.value || !iframeRef.value.contentWindow) return
  
  iframeRef.value.contentWindow.postMessage({
    type: 'sdk-response',
    callId,
    response
  }, '*')
}

// 组件映射
const componentMap = {
  TodoApp: markRaw(TodoApp),
  TextEditorApp: markRaw(TextEditorApp),
  ImageViewerApp: markRaw(ImageViewerApp)
}

// 解析组件
const resolveComponent = (componentName: string) => {
  return componentMap[componentName as keyof typeof componentMap] || null
}

onMounted(() => {
  // 等待iframe加载完成后注入SDK
  if (iframeRef.value) {
    iframeRef.value.addEventListener('load', injectSDK)
  }
  
  // 激活窗口
  activateWindow()
})

onUnmounted(() => {
  // 移除message事件监听
  window.removeEventListener('message', handleMessage)
  
  // 移除iframe load事件监听
  if (iframeRef.value) {
    iframeRef.value.removeEventListener('load', injectSDK)
  }
})
</script>

<style scoped>
.app-window {
  position: absolute;
  background-color: white;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
  transition: all 0.2s ease;
  overflow: hidden;
}

.app-window.active {
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
}

.app-window.maximized {
  border-radius: 0;
}

.window-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 36px;
  padding: 0 10px;
  background-color: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
  user-select: none;
  cursor: move;
}

.window-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: #303133;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.window-controls {
  display: flex;
  gap: 5px;
}

.control-btn {
  padding: 5px;
  font-size: 16px;
  color: #606266;
  cursor: pointer;
  border: none;
  background: transparent;
}

.minimize-btn:hover {
  color: #409eff;
}

.maximize-btn:hover {
  color: #409eff;
}

.close-btn:hover {
  color: #f56c6c;
}

.window-content {
  flex: 1;
  overflow: hidden;
  position: relative;
}

.app-iframe {
  width: 100%;
  height: 100%;
  border: none;
  display: block;
}

.app-component {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.app-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 20px;
  text-align: center;
}

.resize-handle {
  position: absolute;
  z-index: 10;
}

.resize-handle.top-left {
  top: 0;
  left: 0;
  width: 10px;
  height: 10px;
  cursor: nwse-resize;
}

.resize-handle.top {
  top: 0;
  left: 10px;
  right: 10px;
  height: 5px;
  cursor: ns-resize;
}

.resize-handle.top-right {
  top: 0;
  right: 0;
  width: 10px;
  height: 10px;
  cursor: nesw-resize;
}

.resize-handle.right {
  top: 10px;
  right: 0;
  width: 5px;
  bottom: 10px;
  cursor: ew-resize;
}

.resize-handle.bottom-right {
  bottom: 0;
  right: 0;
  width: 10px;
  height: 10px;
  cursor: nwse-resize;
}

.resize-handle.bottom {
  bottom: 0;
  left: 10px;
  right: 10px;
  height: 5px;
  cursor: ns-resize;
}

.resize-handle.bottom-left {
  bottom: 0;
  left: 0;
  width: 10px;
  height: 10px;
  cursor: nesw-resize;
}

.resize-handle.left {
  top: 10px;
  left: 0;
  width: 5px;
  bottom: 10px;
  cursor: ew-resize;
}
</style> 